<!DOCTYPE html>





<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 3.9.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png?v=7.4.0">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png?v=7.4.0">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png?v=7.4.0">
  <link rel="mask-icon" href="/images/logo.svg?v=7.4.0" color="#222">

<link rel="stylesheet" href="/css/main.css?v=7.4.0">


<link rel="stylesheet" href="/lib/font-awesome/css/font-awesome.min.css?v=4.7.0">


<script id="hexo-configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Pisces',
    version: '7.4.0',
    exturl: false,
    sidebar: {"position":"left","display":"post","offset":12,"onmobile":false},
    copycode: {"enable":false,"show_result":false,"style":null},
    back2top: {"enable":true,"sidebar":false,"scrollpercent":false},
    bookmark: {"enable":false,"color":"#222","save":"auto"},
    fancybox: false,
    mediumzoom: false,
    lazyload: false,
    pangu: false,
    algolia: {
      appID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    },
    localsearch: {"enable":false,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},
    path: '',
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    translation: {
      copy_button: '复制',
      copy_success: '复制成功',
      copy_failure: '复制失败'
    },
    sidebarPadding: 40
  };
</script>


<script data-ad-client="ca-pub-8048531516491146" async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>

  <meta name="description" content="一、概念理解OpenGL中，GPU屏幕渲染有以下两种方式：  On-Screen Rendering  意为当前屏幕渲染，指的是GPU的渲染操作是在当前用于显示的屏幕缓冲区中进行。  Off-Screen Rendering  意为离屏渲染，指的是GPU在当前屏幕缓冲区以外新开辟一个缓冲区进行渲染操作。">
<meta name="keywords" content="iPhone, iOS, 离屏渲染">
<meta property="og:type" content="article">
<meta property="og:title" content="离屏渲染学习笔记">
<meta property="og:url" content="http://foogry.org/2015/05/06/2015-05-06-chi-ping-xuan-ran-xue-xi-bi-ji/index.html">
<meta property="og:site_name" content="foogry的技术博客">
<meta property="og:description" content="一、概念理解OpenGL中，GPU屏幕渲染有以下两种方式：  On-Screen Rendering  意为当前屏幕渲染，指的是GPU的渲染操作是在当前用于显示的屏幕缓冲区中进行。  Off-Screen Rendering  意为离屏渲染，指的是GPU在当前屏幕缓冲区以外新开辟一个缓冲区进行渲染操作。">
<meta property="og:locale" content="zh-CN">
<meta property="og:updated_time" content="2019-09-24T12:14:54.777Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="离屏渲染学习笔记">
<meta name="twitter:description" content="一、概念理解OpenGL中，GPU屏幕渲染有以下两种方式：  On-Screen Rendering  意为当前屏幕渲染，指的是GPU的渲染操作是在当前用于显示的屏幕缓冲区中进行。  Off-Screen Rendering  意为离屏渲染，指的是GPU在当前屏幕缓冲区以外新开辟一个缓冲区进行渲染操作。">
  <link rel="canonical" href="http://foogry.org/2015/05/06/2015-05-06-chi-ping-xuan-ran-xue-xi-bi-ji/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome: false,
    isPost: true,
    isPage: false,
    isArchive: false
  };
</script>

  <title>离屏渲染学习笔记 | foogry的技术博客</title>
  


  <script>
    var _hmt = _hmt || [];
    (function() {
      var hm = document.createElement("script");
      hm.src = "https://hm.baidu.com/hm.js?2944231de73b405a5da5c6b4097cfa0e";
      var s = document.getElementsByTagName("script")[0];
      s.parentNode.insertBefore(hm, s);
    })();
  </script>






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .logo,
  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-CN">
  <div class="container use-motion">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-meta">

    <div>
      <a href="/" class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">foogry的技术博客</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
        <h1 class="site-subtitle" itemprop="description">Stay hungry,stay foolish.</h1>
      
  </div>

  <div class="site-nav-toggle">
    <button aria-label="切换导航栏">
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>


<nav class="site-nav">
  
  <ul id="menu" class="menu">
      
      
      
        
        <li class="menu-item menu-item-home">
      
    

    <a href="/" rel="section"><i class="menu-item-icon fa fa-fw fa-home"></i> <br>首页</a>

  </li>
      
      
      
        
        <li class="menu-item menu-item-archives">
      
    

    <a href="/archives/" rel="section"><i class="menu-item-icon fa fa-fw fa-archive"></i> <br>归档</a>

  </li>
      
      
      
        
        <li class="menu-item menu-item-about">
      
    

    <a href="/about/" rel="section"><i class="menu-item-icon fa fa-fw fa-user"></i> <br>关于</a>

  </li>
  </ul>

</nav>
</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>


    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
            

          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
      <article itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block post">
    <link itemprop="mainEntityOfPage" href="http://foogry.org/2015/05/06/2015-05-06-chi-ping-xuan-ran-xue-xi-bi-ji/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="foogry">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/images/avatar.gif">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="foogry的技术博客">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">离屏渲染学习笔记

          
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              
                
              

              <time title="创建时间：2015-05-06 17:17:55" itemprop="dateCreated datePublished" datetime="2015-05-06T17:17:55+08:00">2015-05-06</time>
            </span>
          
            

            
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2019-09-24 20:14:54" itemprop="dateModified" datetime="2019-09-24T20:14:54+08:00">2019-09-24</time>
              </span>
            
          
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/iOS/" itemprop="url" rel="index"><span itemprop="name">iOS</span></a></span>

                
                
              
            </span>
          

          
  
  <span class="post-meta-item">
    
      <span class="post-meta-item-icon">
        <i class="fa fa-comment-o"></i>
      </span>
        
      
      <span class="post-meta-item-text">Valine：</span>
    
    <a title="valine" href="/2015/05/06/2015-05-06-chi-ping-xuan-ran-xue-xi-bi-ji/#comments" itemprop="discussionUrl"><span class="post-comments-count valine-comment-count" data-xid="/2015/05/06/2015-05-06-chi-ping-xuan-ran-xue-xi-bi-ji/" itemprop="commentCount"></span></a>
  </span>
  
  

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
        <h2 id="一、概念理解"><a href="#一、概念理解" class="headerlink" title="一、概念理解"></a>一、概念理解</h2><p>OpenGL中，GPU屏幕渲染有以下两种方式：</p>
<ul>
<li>On-Screen Rendering</li>
</ul>
<p>意为当前屏幕渲染，指的是GPU的渲染操作是在当前用于显示的屏幕缓冲区中进行。</p>
<ul>
<li>Off-Screen Rendering</li>
</ul>
<p>意为离屏渲染，指的是GPU在当前屏幕缓冲区以外新开辟一个缓冲区进行渲染操作。</p>
<a id="more"></a>

<h2 id="二、离屏渲染的是是非非"><a href="#二、离屏渲染的是是非非" class="headerlink" title="二、离屏渲染的是是非非"></a>二、离屏渲染的是是非非</h2><p>相比于当前屏幕渲染，离屏渲染的代价是很高的，主要体现在两个方面：</p>
<ul>
<li>创建新缓冲区</li>
</ul>
<p>要想进行离屏渲染，首先要创建一个新的缓冲区。</p>
<ul>
<li>上下文切换</li>
</ul>
<p>离屏渲染的整个过程，需要多次切换上下文环境：先是从当前屏幕（On-Screen）切换到离屏（Off-Screen）；等到离屏渲染结束以后，将离屏缓冲区的渲染结果显示到屏幕上有需要将上下文环境从离屏切换到当前屏幕。而上下文环境的切换是要付出很大代价的。</p>
<h2 id="三、离屏渲染触发方式"><a href="#三、离屏渲染触发方式" class="headerlink" title="三、离屏渲染触发方式"></a>三、离屏渲染触发方式</h2><p>设置了以下属性时，都会触发离屏绘制：</p>
<ul>
<li>shouldRasterize（光栅化）</li>
<li>masks（遮罩）</li>
<li>shadows（阴影）</li>
<li>edge antialiasing（抗锯齿）</li>
<li>group opacity（不透明）</li>
</ul>
<p>需要注意的是，如果shouldRasterize被设置成YES，在触发离屏绘制的同时，会将光栅化后的内容缓存起来，如果对应的layer及其sublayers没有发生改变，在下一帧的时候可以直接复用。这将在很大程度上提升渲染性能。</p>
<p>而其它属性如果是开启的，就不会有缓存，离屏绘制会在每一帧都发生。</p>
<h2 id="四、另一种特殊的“离屏渲染”"><a href="#四、另一种特殊的“离屏渲染”" class="headerlink" title="四、另一种特殊的“离屏渲染”"></a>四、另一种特殊的“离屏渲染”</h2><p>按照之前的说法，如果将不在GPU的当前屏幕缓冲区中进行的渲染都称为离屏渲染，那么就还有另一种特殊的“离屏渲染”方式：<code>CPU渲染</code>。</p>
<p>如果我们重写了drawRect方法，并且使用任何Core Graphics的技术进行了绘制操作，就涉及到了CPU渲染。整个渲染过程由CPU在App内<code>同步地</code>完成，渲染得到的bitmap最后再交由GPU用于显示。</p>
<h2 id="五、Instruments"><a href="#五、Instruments" class="headerlink" title="五、Instruments"></a>五、Instruments</h2><p>Instruments的Core Animation工具中有几个和离屏渲染相关的检查选项：</p>
<ul>
<li>Color Offscreen-Rendered Yellow </li>
</ul>
<p>开启后会把那些需要离屏渲染的图层高亮成黄色，这就意味着黄色图层可能存在性能问题。</p>
<ul>
<li>Color Hits Green and Misses Red</li>
</ul>
<p>如果shouldRasterize被设置成YES，对应的渲染结果会被缓存，如果图层是绿色，就表示这些缓存被复用；如果是红色就表示缓存会被重复创建，这就表示该处存在性能问题了。</p>
<h2 id="六、如何抉择"><a href="#六、如何抉择" class="headerlink" title="六、如何抉择"></a>六、如何抉择</h2><p>现在摆在我们面前得有三个选择：当前屏幕渲染、离屏渲染、CPU渲染，该用哪个呢？这需要根据具体的使用场景来决定。</p>
<ul>
<li>尽量使用当前屏幕渲染</li>
</ul>
<p>鉴于离屏渲染、CPU渲染可能带来的性能问题，一般情况下，我们要尽量使用当前屏幕渲染。</p>
<ul>
<li>离屏渲染 VS CPU渲染</li>
</ul>
<p>由于GPU的浮点运算能力比CPU强，CPU渲染的效率可能不如离屏渲染；但如果仅仅是实现一个简单的效果，直接使用CPU渲染的效率又可能比离屏渲染好，毕竟离屏渲染要涉及到缓冲区创建和上下文切换等耗时操作。</p>
<p>总之，具体的选择应该由性能测试结果来决定。</p>
<h2 id="七、写在最后"><a href="#七、写在最后" class="headerlink" title="七、写在最后"></a>七、写在最后</h2><p>在赵岩同学的点拨下才理解了离屏渲染的概念，在此表示感谢！</p>
<p>如理解有误还请大家指出。</p>
<h2 id="参考文档"><a href="#参考文档" class="headerlink" title="参考文档"></a>参考文档</h2><ul>
<li><p><a href="http://www.objc.io/issue-3/moving-pixels-onto-the-screen.html" target="_blank" rel="noopener">Getting Pixels onto the Screen</a> (中文翻译版：<a href="http://objccn.io/issue-3-1/" target="_blank" rel="noopener">绘制像素到屏幕上</a>)</p>
</li>
<li><p><a href="https://robots.thoughtbot.com/designing-for-ios-graphics-performance" target="_blank" rel="noopener">Designing for iOS: Graphics &amp; Performance</a>  (中文翻译版：<a href="http://www.taofengping.com/2013/05/18/designing-for-ios-graphics-performance/#.VUinciGqpBc" target="_blank" rel="noopener">iOS图形处理和性能</a>)</p>
</li>
<li><p><a href="https://lobste.rs/s/ckm4uw/a_performance-minded_take_on_ios_design" target="_blank" rel="noopener">a performance minded take on ios design</a>  (中文翻译版：<a href="http://www.taofengping.com/2013/05/18/ios_offscreen_analysis/#.VUinPyGqpBd" target="_blank" rel="noopener">iOS离屏绘制的性能和机制分析</a>)</p>
</li>
</ul>

    </div>

    
    
    
        
      
        <div id="reward-container">
  <div></div>
  <button id="reward-button" disable="enable" onclick="var qr = document.getElementById(&quot;qr&quot;); qr.style.display = (qr.style.display === 'none') ? 'block' : 'none';">
    打赏
  </button>
  <div id="qr" style="display: none;">
        
      
      <div style="display: inline-block">
        <img src="/images/weixinpay.jpg" alt="foogry 微信支付">
        <p>微信支付</p>
      </div>

  </div>
</div>

      
        

<div>
<ul class="post-copyright">
  <li class="post-copyright-author">
    <strong>本文作者： </strong>foogry</li>
  <li class="post-copyright-link">
    <strong>本文链接：</strong>
    <a href="http://foogry.org/2015/05/06/2015-05-06-chi-ping-xuan-ran-xue-xi-bi-ji/" title="离屏渲染学习笔记">http://foogry.org/2015/05/06/2015-05-06-chi-ping-xuan-ran-xue-xi-bi-ji/</a>
  </li>
  <li class="post-copyright-license">
    <strong>版权声明： </strong>本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-nd/4.0/deed.zh" rel="noopener" target="_blank"><i class="fa fa-fw fa-creative-commons"></i>BY-NC-ND</a> 许可协议。转载请注明出处！</li>
</ul>
</div>

      

      <footer class="post-footer">
          
            
          
          <div class="post-tags">
            
              <a href="/tags/iOS/" rel="tag"># iOS</a>
            
              <a href="/tags/iPhone/" rel="tag"># iPhone</a>
            
              <a href="/tags/离屏渲染/" rel="tag"># 离屏渲染</a>
            
          </div>
        

        

          <div class="post-nav">
            <div class="post-nav-next post-nav-item">
              
                <a href="/2014/10/13/2014-10-13-shou-dong-nei-cun-guan-li-zhuan-arcxiang-mu-shi-zhan/" rel="next" title="手动内存管理转ARC项目实战">
                  <i class="fa fa-chevron-left"></i> 手动内存管理转ARC项目实战
                </a>
              
            </div>

            <span class="post-nav-divider"></span>

            <div class="post-nav-prev post-nav-item">
              
                <a href="/2015/07/27/2015-07-27-ru-he-shou-dong-jie-xi-crashlog/" rel="prev" title="手动解析CrashLog之----方法篇">
                  手动解析CrashLog之----方法篇 <i class="fa fa-chevron-right"></i>
                </a>
              
            </div>
          </div>
        
      </footer>
    
  </div>
  
  
  
  </article>

  </div>


          </div>
          
    
    <div class="comments" id="comments"></div>
  

        </div>
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">
        
        
        
        
      

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
          <div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#一、概念理解"><span class="nav-number">1.</span> <span class="nav-text">一、概念理解</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#二、离屏渲染的是是非非"><span class="nav-number">2.</span> <span class="nav-text">二、离屏渲染的是是非非</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#三、离屏渲染触发方式"><span class="nav-number">3.</span> <span class="nav-text">三、离屏渲染触发方式</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#四、另一种特殊的“离屏渲染”"><span class="nav-number">4.</span> <span class="nav-text">四、另一种特殊的“离屏渲染”</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#五、Instruments"><span class="nav-number">5.</span> <span class="nav-text">五、Instruments</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#六、如何抉择"><span class="nav-number">6.</span> <span class="nav-text">六、如何抉择</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#七、写在最后"><span class="nav-number">7.</span> <span class="nav-text">七、写在最后</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#参考文档"><span class="nav-number">8.</span> <span class="nav-text">参考文档</span></a></li></ol></div>
        
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
  <p class="site-author-name" itemprop="name">foogry</p>
  <div class="site-description" itemprop="description"></div>
</div>
  <nav class="site-state motion-element">
      <div class="site-state-item site-state-posts">
        
          <a href="/archives/">
        
          <span class="site-state-item-count">22</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
    
      
      
      <div class="site-state-item site-state-categories">
        
        <span class="site-state-item-count">8</span>
        <span class="site-state-item-name">分类</span>
        
      </div>
    
      
      
      <div class="site-state-item site-state-tags">
        
        <span class="site-state-item-count">56</span>
        <span class="site-state-item-name">标签</span>
        
      </div>
    
  </nav>
  <div class="cc-license motion-element" itemprop="license">
    
  
    <a href="https://creativecommons.org/licenses/by-nc-nd/4.0/deed.zh" class="cc-opacity" rel="noopener" target="_blank"><img src="/images/cc-by-nc-nd.svg" alt="Creative Commons"></a>
  </div>



      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">&copy; <span itemprop="copyrightYear">2020</span>
  <span class="with-love" id="animate">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">foogry</span>
</div>
  <div class="powered-by">Hosted by <a href="https://coding.net/pages" class="theme-link" rel="noopener" target="_blank">Coding Pages</a></div>
  <span class="post-meta-divider">|</span>
  <div class="powered-by">由 <a href="https://hexo.io" class="theme-link" rel="noopener" target="_blank">Hexo</a> 强力驱动 v3.9.0</div>
  <span class="post-meta-divider">|</span>
  <div class="theme-info">主题 – <a href="https://theme-next.org" class="theme-link" rel="noopener" target="_blank">NexT.Pisces</a> v7.4.0</div>

        












        
      </div>
    </footer>
  </div>

  


  <script src="/lib/anime.min.js?v=3.1.0"></script>
  <script src="/lib/velocity/velocity.min.js?v=1.2.1"></script>
  <script src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
<script src="/js/utils.js?v=7.4.0"></script><script src="/js/motion.js?v=7.4.0"></script>
<script src="/js/schemes/pisces.js?v=7.4.0"></script>
<script src="/js/next-boot.js?v=7.4.0"></script>



  





















  

  

  


<script>
NexT.utils.getScript('//unpkg.com/valine/dist/Valine.min.js', () => {
  var GUEST = ['nick', 'mail', 'link'];
  var guest = 'nick,mail,link';
  guest = guest.split(',').filter(item => {
    return GUEST.includes(item);
  });
  new Valine({
    el: '#comments',
    verify: false,
    notify: false,
    appId: 'vqsvFaA8FXndr4867HJvtJ7P-gzGzoHsz',
    appKey: '6L6ddsrLCJVMetc2W7CL9kkf',
    placeholder: 'Comment Here',
    avatar: 'mm',
    meta: guest,
    pageSize: '10' || 10,
    visitor: false,
    lang: 'zh-cn' || 'zh-cn',
    path: location.pathname
  });
}, window.Valine);
</script>

</body>
</html>
